/*
 * FileName: poll.cc
 * Author: 李波(Edwin Lee)
 * Date: 2024-04-24 18:00:51
 * Version: 1.0
 * Description: 
 */

#include <stdio.h>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include <poll.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/fcntl.h>
#include <list>
#include <queue>

//初始化服务端的监听端口
int initserver(int port);
int Accept(int lfd, struct sockaddr *sa, socklen_t *salenptr);

int main(int argc,char* argv[])
{
	if(argc!=2)
	{
		printf("usage:./poll 6666\n");
		return -1;
	}
	
	//初始化服务端用于监听的socket
	int lfd = initserver(atoi(argv[1]));
	printf("listensock=%d\n",lfd);
	if(lfd<0)
	{
		printf("initserver() failed\n");
		return -1;
	}
	std::list<int> fdlist;
	std::queue<int> deleteque;
	fdlist.push_back(lfd);
	struct pollfd fds[1024];
	for(int i=0; i<1024; ++i)
	{
		fds[i].fd=-1;
	}
	fds[lfd].fd=lfd;
	fds[lfd].events=POLLIN;
	int ret=0;
	char buf[1500]{0};
	int maxfd = lfd;
	for(;;)
	{
		if(0 > (ret=poll(fds,maxfd+1,-1)))
		{
			perror("poll failed");
			return -1;
		}
		else if (0==ret) 
		{
			continue;
		}
		for(auto it=fdlist.begin();it!=fdlist.end();++it)
		{
			if((fds[*it].revents&POLLIN) != 0)
			{
				printf("*it=%d\n",*it);
				if(lfd == *it)
				{
					struct sockaddr_in cliaddr;
					socklen_t len = sizeof cliaddr;
					int cfd = accept(lfd,(struct sockaddr *)&cliaddr, &len);
					if(cfd<0)
					{
						perror("accept() failed");
						continue;
					}
					printf("new client ip=%s port=%d\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
					fdlist.push_back(cfd);
					fds[cfd].fd = cfd;
					fds[cfd].events=POLLIN;
					if(maxfd<cfd)
						maxfd=cfd;
					continue;
				}
				else 
				{
					memset(buf,0,sizeof buf);
					int n = recv(*it, buf, sizeof(buf)-1,0);
					if(n<=0)
					{
						perror("read failed");
						close(*it);
						fds[*it].fd = -1;
						deleteque.push(*it);
						printf("close cfd=%d\n",*it);
						if((*it)==maxfd)
						{
							for(int i=maxfd-1; i>2; ++i)
							{
								if(fds[i].fd != -1)
								{
									maxfd = i;
									printf("maxfd=%d\n",maxfd);
									break;
								}
							}
						}
						continue;
					}
					printf("recv:%s\n",buf);
					//注意这里第三个参数填strlen(),而不是sizeof()
					send(*it, buf, strlen(buf),0);	
				}
			}
		}
		while(!deleteque.empty())
		{
			fdlist.remove(deleteque.front());
			deleteque.pop();
		}

	}
	return 0;
}


int initserver(int port)
{
	int lfd = socket(AF_INET, SOCK_STREAM, 0);
	if(lfd<0)
	{
		perror("socket() failed");
		return -1;
	}
	//设置lfd的地址复用(未理解)
	int opt = 1;
	setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);

	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	//设置任何人都能访问
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(port);
	
	if(bind(lfd,(struct sockaddr*)&servaddr,sizeof servaddr)<0)
	{
		perror("bind() failed");
		close(lfd);
		return -1;
	}
	if(listen(lfd,128)!=0)
	{
		perror("listen() failed");
		close(lfd);
		return -1;
	}
	return lfd;
}

